import {expect} from 'chai';
import * as sinon from 'sinon';
import * as step from '../../src';
import proxyquire from 'proxyquire'
import * as skip from '../../src/oss/skip'

import {RemoteStorage, PutObjectResult, UserMeta, NormalSuccessResponse} from '../../src/oss/storage'
import {UPLOAD_FILE_MAX_SIZE, uploadWithUpdate} from '../../src/oss/upload'

let remoteStorage: RemoteStorage;
let statStub: sinon.SinonStub;
let putStub: sinon.SinonStub;
let getStub: sinon.SinonStub;
let headStub: sinon.SinonStub;

const sandbox = sinon.createSandbox();
let stepExecStub: sinon.SinonStub;

describe('upload', () => {
    beforeEach(() => {
        stepExecStub = sandbox.stub(step.exec, 'call').returns(Promise.resolve(0));

        statStub = sandbox.stub();
        putStub = sandbox.stub();
        getStub = sandbox.stub();
        headStub = sandbox.stub();
        remoteStorage = {
            put: putStub,
            get: getStub,
            head: headStub,
            stat: statStub
        }
    });

    afterEach(() => {
        sandbox.restore();
    });


    const fsStub = {
        statSync: sinon.stub(),
        existsSync: sinon.stub(),
    };
    const {upload} = proxyquire('../../src/oss/upload', {
        fs: fsStub
    })

    it('should skip upload when file not exists', async () => {

        const artifactFullName = 'test/oss/test.file';
        fsStub.existsSync.returns(false);

        await upload(remoteStorage,  artifactFullName,"sss",{});

        expect(putStub.called).to.be.false;
    })

    it('should skip upload when no object key', async () => {

        const artifactFullName = 'test/oss/test.file';
        fsStub.existsSync.returns(false);

        await upload(remoteStorage,  artifactFullName,"",{});

        expect(putStub.called).to.be.false;
    })

    it('should upload  file successfully', async () => {
        const artifactFullName = 'artifact-full-name';
        fsStub.existsSync.returns(true);

        const putObjectResult: PutObjectResult = {
            name: '',
            url: '',
            data: {},
            res: {
                status: 200,
                size: 0,
                rt: 0,
                headers:{}
            }
        };
        putStub.resolves(putObjectResult);

        fsStub.statSync.returns({size: 100});
        await upload(remoteStorage, artifactFullName,"ss",{});

        expect(putStub.calledOnceWith("ss", artifactFullName, {
            headers: {}
        })).to.be.true;
    });

    it('should skip cache upload if cache file size exceeds max size limit', async () => {
        const artifactFullName = 'artifact-full-name';
        fsStub.existsSync.returns(true);

        fsStub.statSync.returns({size: Number(UPLOAD_FILE_MAX_SIZE + 100)});

        await upload(remoteStorage, artifactFullName,"s",{});

        expect(putStub.called).to.be.false;
    });
});


describe('uploadWithUpdate', () => {
    let skipUploadStub: sinon.SinonStub;
    beforeEach(() => {
        stepExecStub = sandbox.stub(step.exec, 'call').returns(Promise.resolve(0));

        statStub = sandbox.stub();
        putStub = sandbox.stub();
        getStub = sandbox.stub();
        headStub = sandbox.stub();
        skipUploadStub = sandbox.stub(skip, 'skipUpload');
        remoteStorage = {
            put: putStub,
            get: getStub,
            head: headStub,
            stat: statStub
        }
    });

    afterEach(() => {
        sandbox.restore();
    });


    const fsStub = {
        statSync: sinon.stub(),
        existsSync: sinon.stub(),
    };


    it('should upload file successfully', async () => {
        const artifactFullName = 'artifact-full-name';
        fsStub.existsSync.returns(true);
        fsStub.statSync.returns(new Date());

        skipUploadStub.resolves(false)

        const uploadWithUpdateProxy = proxyquire('../../src/oss/upload', {
            fs: fsStub,
            'skip/skipUpload': skipUploadStub
        }).uploadWithUpdate;

        const putObjectResult: PutObjectResult = {
            name: '',
            url: '',
            data: {},
            res: {
                status: 200,
                size: 0,
                rt: 0,
                headers:{}
            }
        };
        putStub.resolves(putObjectResult);

        await uploadWithUpdateProxy(remoteStorage, artifactFullName, "ss",{});

        expect(putStub.calledOnceWith("ss", artifactFullName, {
            headers: {}
        })).to.be.true;
    });

    it('should skip ', async () => {
        const artifactFullName = 'artifact-full-name';
        fsStub.existsSync.returns(true);
        fsStub.statSync.returns(new Date());

        skipUploadStub.resolves(true)

        const uploadWithUpdateProxy = proxyquire('../../src/oss/upload', {
            fs: fsStub,
            'skip/skipUpload': skipUploadStub
        }).uploadWithUpdate;

        await uploadWithUpdateProxy(remoteStorage, artifactFullName, "s",{});

        expect(putStub.called).to.be.false;
    });
});

